/*
 * Lenovo Group
 * Copyright (c) 2015-2016 All Rights Reserved.
 * Project Name: lmrp-android app
 * Create Time: 16-2-16 下午6:48
 */

package com.lenovo.mso2o;

import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.os.StrictMode;
import android.text.TextUtils;

import com.baidu.mapapi.SDKInitializer;
import com.github.lzyzsd.jsbridge.BridgeWebView;
import com.igexin.sdk.PushManager;
import com.lenovo.framework.FApplication;
import com.lenovo.framework.base.FBaseActivity;
import com.lenovo.framework.biz.ContextManager;
import com.lenovo.framework.util.CompatHelper;
import com.lenovo.framework.util.DLog;
import com.lenovo.framework.util.FPreferenceManager;
import com.lenovo.framework.util.FileHelper;
import com.lenovo.mso2o.biz.FDevOpenHelper;
import com.lenovo.mso2o.conf.MSConstants;
import com.lenovo.mso2o.entity.g.DaoMaster;
import com.lenovo.mso2o.entity.g.DaoSession;
import com.lenovo.mso2o.ui.MainActivity;
import com.lenovo.mso2o.util.CommonUtil;

import java.io.File;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * Customized applicaction instance with crossing app lifecycle components like
 * rxbus,refwatcher, greendaosession and so on.
 *
 * @author JeffreyHe
 * @version 1.0
 * @updated 17-一月-2016 14:05:24
 */
public class MSApplication extends FApplication {

    /**
     * greendao master to create session used for this app
     */
    private static DaoMaster mDaoMaster;
    //greendao session used by this app
    private static DaoSession mDaoSession;
    /**
     * datadir for file saving
     */
    private static String dataDir;

    /**
     * cachedir in the datadir
     */
    private static File cacheDir;
    //do not crash here!!!
    private Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
            //TODO upload crash log
            DLog.p(paramThrowable);
            FBaseActivity.finishAll();
            System.exit(0);
            Intent intent = new Intent(ContextManager.context(), MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            ContextManager.appContext().startActivity(intent);
        }
    };

    @Override
    public void onCreate() {
        FApplication.DEBUG = BuildConfig.DEBUG;
        super.onCreate();
        if (BuildConfig.DEBUG) {
            enableStrictMode();
        }
        Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
        if(handler == null || handler != MSApplication.this.handler)
            Thread.setDefaultUncaughtExceptionHandler(handler);

        //初始化SDK
        Observable.create(
        new Observable.OnSubscribe<Class>() {
            @Override
            public void call(Subscriber<? super Class> subscriber) {
                Class[] classes = new Class[]{
                        PushManager.class,
                        SDKInitializer.class
                         };
                for(Class c : classes)
                    subscriber.onNext(c);
            }
        })
        .doOnSubscribe(new Action0() {
            @Override
            public void call() {
                dataDir = CommonUtil.getOwnedDataDir(MSApplication.this);
                ContextManager.initDataDir(dataDir);
                cacheDir = new File(dataDir + "/cache/");
                BridgeWebView.CACHE_DIR = cacheDir.getAbsolutePath();
                FileHelper.ensureDir(cacheDir.getPath());
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(Schedulers.newThread())
        .map(new Func1<Class, Object>() {
            @Override
            public Object call(Class aClass) {
                DLog.w(MSApplication.class
                        .getName(), aClass.getName() + " initializing");
                if (PushManager.class.getName().equals(aClass.getName())) {
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            PushManager.getInstance().initialize(MSApplication.this);
                            PushManager.getInstance().turnOnPush(MSApplication.this);
                            String cid = PushManager.getInstance().getClientid(MSApplication.this);
                            DLog.w("cid", cid);
                            if(cid != null && !TextUtils.isEmpty(cid))
                                FPreferenceManager.putString(MSConstants.KEY_GETUI_CID, cid);
                        }
                    });
                } else if (SDKInitializer.class.getName().equals(aClass.getName())) {
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            SDKInitializer.initialize(getApplicationContext());
                        }
                    });
                }
                return aClass;
            }
        })
        .subscribe(new Action1<Object>() {
            @Override
            public void call(Object o) {
                DLog.w(MSApplication.class
                        .getName(), o.toString() + " init finished");
            }
        });

    }

    public synchronized static DaoMaster getDaoMaster() {
        if (mDaoMaster == null) {
            //create database
            DaoMaster.OpenHelper helper = new FDevOpenHelper(ContextManager.context(), MSConstants.DataConstants.DB_NAME, null);
            mDaoMaster = new DaoMaster(helper.getWritableDatabase());
        }
        return mDaoMaster;
    }

    public synchronized static DaoSession getDaoSession() {
        if (mDaoSession == null) {
            mDaoSession = getDaoMaster().newSession();
        }
        return mDaoSession;
    }

    public static String getDataDir() {
        return dataDir;
    }

    public static File getCachedDir() {
        return cacheDir;
    }

    private static void enableStrictMode() {
        if(CompatHelper.hasGingerbread())
        {
            StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
                    new StrictMode.ThreadPolicy.Builder()
                            .detectAll()
                            .penaltyLog();
            StrictMode.VmPolicy.Builder vmPolicyBuilder =
                    new StrictMode.VmPolicy.Builder()
                            .detectAll()
                            .penaltyLog();

            if (CompatHelper.hasHoneycomb()) {
                threadPolicyBuilder.penaltyFlashScreen();
                vmPolicyBuilder.setClassInstanceLimit(MainActivity.class, 1);
            }
            StrictMode.setThreadPolicy(threadPolicyBuilder.build());
            StrictMode.setVmPolicy(vmPolicyBuilder.build());
        }
    }
}
